package com.csx.base.concurrency.threadlocal;

import com.csx.base.concurrency.util.TimeUtil;

import java.util.concurrent.TimeUnit;

/**
 * <p> what does this class do ? </p>
 *   该案例是 ThreadLocal 的基本使用案例
 * <p> How does it work ?</p>
 * <p> Why does it do this ?</p>
 *
 * @author cuisongxu
 * @date 2024/12/4 周三 15:35
 */
public class ThreadLocalTest {

    public static void main(String[] args) {
        ThreadLocalTest threadLocalTest = new ThreadLocalTest();
        threadLocalTest.test();
    }


    public void test() {

        // 创建并启动三个线程
        Thread thread1 = new Thread(new GetConnectTask(), "thread1");
        Thread thread2 = new Thread(new GetConnectTask(), "thread2");
        Thread thread3 = new Thread(new GetConnectTask(), "thread3");
        thread1.start();
        thread2.start();
        thread3.start();

        // 等待所有线程执行完毕
        try {
            thread1.join();
            thread2.join();
            thread3.join();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

    }

    static class GetConnectTask implements Runnable {

        @Override
        public void run() {
            DatabaseConnection connection = DBUtils.getConnection();
            String connectionInfo = connection.getConnectionInfo();
            String nowTimeStr = TimeUtil.getNowTimeStr();
            System.out.println(nowTimeStr + " "  + Thread.currentThread().getName() + "获取的连接 connectionInfo: " + connectionInfo);

            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

            DatabaseConnection connection2 = DBUtils.getConnection();
            String connectionInfo2 = connection2.getConnectionInfo();
            nowTimeStr = TimeUtil.getNowTimeStr();
            System.out.println(nowTimeStr + " "  + Thread.currentThread().getName() + "第二次获取的连接 connectionInfo: " + connectionInfo2);
        }
    }


    static class DBUtils {

        private static final ThreadLocal<DatabaseConnection> connectionHolder = new ThreadLocal<DatabaseConnection>() {
            @Override
            protected DatabaseConnection initialValue() {
                return new DatabaseConnection(Thread.currentThread().getName() + " 创建的连接");
            }
        };

        public static DatabaseConnection getConnection() {
            return connectionHolder.get();
        }

    }

    static class DatabaseConnection {

        private String connectionInfo;

        public DatabaseConnection(String connectionInfo) {
            this.connectionInfo = connectionInfo;
        }

        public String getConnectionInfo() {
            return connectionInfo;
        }

        public void setConnectionInfo(String connectionInfo) {
            this.connectionInfo = connectionInfo;
        }
    }
}
